package cn.mrcode.wxsdk.web.service;


import cn.mrcode.wxsdk.core.dialogue.common.RandomStringGenerator;
import cn.mrcode.wxsdk.core.dialogue.common.SignUtil;
import cn.mrcode.wxsdk.core.dialogue.common.util.DateUtil;
import cn.mrcode.wxsdk.core.dialogue.service.BaseService;
import cn.mrcode.wxsdk.web.common.AuthorizeUrl;
import cn.mrcode.wxsdk.web.common.PaySignature;
import cn.mrcode.wxsdk.web.common.ticket.lifeCycle.ITicketService;
import cn.mrcode.wxsdk.web.protocol.base.JsSdkAuthorityData;
import cn.mrcode.wxsdk.web.protocol.res.UnifiedOrderResData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * 微信jssdk相关服务
 * @author zhuqiang
 * @version V1.0
 * @date 2015/9/16 10:30
 */
public class JsSdkService extends BaseService {
    private static Logger log = LoggerFactory.getLogger(JsSdkService.class);
    private static ITicketService iTicketService;

    /**
     * 本方法支持 多公众号获取ticket信息，并且维护Accesstoken的生存时间
     * 如果是分布式的，则不能动态的对新增的 公众号 进行支持
     * @param appid
     * @param secret
     * @return
     */
    public static String getJsApiTicket(String appid, String secret){
        try {
            return iTicketService.getJsApiTicke(appid, secret);
        } catch (Exception e) {
            e.printStackTrace();
            String errMsg = "获取ticket出现了一个致命错误:" + e.getMessage();
            log.error(errMsg);
            throw new RuntimeException(errMsg);
        }
    }
    /**
     * 获取js sdk 配置参数
     * 签名生成规则如下：
     * 参与签名的字段包括noncestr（随机字符串）,
     * 有效的jsapi_ticket,
     * timestamp（时间戳）,
     * url（当前网页的URL，不包含#及其后面部分） 。
     * @return
     */
    public static JsSdkAuthorityData get(String appId, String secret, String url){
        String noncestr = RandomStringGenerator.getRandomStringByLength(32);
        String timestamp = DateUtil.getNowTimestamp();
        //签名
        Map<String,String> map = new HashMap<String, String>();
        map.put("noncestr", noncestr);
        map.put("jsapi_ticket", getJsApiTicket(appId, secret));
        map.put("timestamp", timestamp);
        map.put("url", url.replace("&amp;","&")); //防止页面地址提交的时候，& 符号被自动转义了

        String signature = SignUtil.getMapSignSHA1(map);

        JsSdkAuthorityData result = new JsSdkAuthorityData();
        result.setAppId(appId);
        result.setNonceStr(noncestr);
        result.setTimestamp(timestamp);
        result.setSignature(signature);
        return  result;
    }




    /**
     * 根据统一下单回包数据，生成 js sdk 支付参数
     * 即最后参与签名的参数有appId, timeStamp, nonceStr, package, signType
     * 注意：后台签名 timeStamp  。页面js 接口用的是全小写
     * @param unifiedorder
     * @return
     */
    public static Map<String,String> getChooseWXPayData(UnifiedOrderResData unifiedorder, String key){
        //封装 jssdk 需要的参数信息
        Map<String,String> map = new HashMap<String, String>();
        map.put("appId",unifiedorder.getAppid());
        map.put("timeStamp", DateUtil.getNowTimestamp());
        map.put("nonceStr", RandomStringGenerator.getRandomStringByLength(32));
        map.put("package","prepay_id=" + unifiedorder.getPrepay_id());
        map.put("signType","MD5");
        String sign = PaySignature.getMapSignStr(map, key);
        map.put("paySign", sign);  //签名

        return map;
    }

    /**
     * 生成 网页授权rul
     * @param appId
     * @param redirect_uri 跳转的url 必须携带域名
     * @param snsapi_base  应用授权作用域 AuthorizeUrl 中有静态常量,为空 则默认 使用base作用域
     * @return
     */
    public static String createAuthorizeUrl(String appId, String redirect_uri, String snsapi_base) {
        if(AuthorizeUrl.SCOPE_SNSAPI_USERINFO.equalsIgnoreCase(snsapi_base)){
            snsapi_base = AuthorizeUrl.SCOPE_SNSAPI_USERINFO;
        }else{
            snsapi_base = AuthorizeUrl.SCOPE_SNSAPI_BASE;
        }
        AuthorizeUrl.ConcreteBuilder builder = new AuthorizeUrl.ConcreteBuilder(appId, redirect_uri, snsapi_base);
        String url = builder.builder().createUrl();
        return url;
    }
}
